﻿/* Copyright 2010 Igor Francé
 * 
 * This file is part of ECMADoc (http://ecmadoc.codeplex.com).
 * 
 * ECMADoc is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License 
 * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * ECMADoc is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with ECMADoc. 
 * If not, see http://www.gnu.org/licenses/.
 */
namespace EcmaDoc.Core.Configuration
{
	using System.Collections.Specialized;
	using System.Text.RegularExpressions;
	using System.Xml;

	using Items;

	/// <summary>
	/// Provides a definition of a token.
	/// </summary>
	public class TokenInfo
	{
		private readonly NameValueCollection matchMap = new NameValueCollection();

		/// <summary>
		/// Initializes a new instance of the <see cref="TokenInfo"/> class.
		/// </summary>
		/// <param name="tokenNode">The XML element that defines the token.</param>
		public TokenInfo(XmlElement tokenNode)
		{
			this.Name = tokenNode.GetAttribute("name").Replace("@", string.Empty);
			this.Handler = tokenNode.GetAttribute("handler");
			this.Value = tokenNode.GetAttribute("value");

			this.MatchPattern = tokenNode.GetAttribute("match");
			if (!string.IsNullOrEmpty(this.MatchPattern))
			{
				Match m = Regex.Match(this.MatchPattern, @"\(\?'([^']+)'");
				while (m.Success)
				{
					string matchNum = (this.matchMap.Count + 1).ToString(); 
					string matchName = m.Groups[1].Value;

					this.matchMap[matchNum] = matchName;
					m = m.NextMatch();
				}
			}
		}

		/// <summary>
		/// Gets the name of this token.
		/// </summary>
		public string Name { get; private set; }

		/// <summary>
		/// Gets the detail that this token sets
		/// </summary>
		public string Handler { get; private set; }

		/// <summary>
		/// Gets the value that this token sets
		/// </summary>
		public string Value { get; private set; }

		/// <summary>
		/// Gets the value that this token sets
		/// </summary>
		public string MatchPattern { get; private set; }

		/// <summary>
		/// Parses the value of the specified token.
		/// </summary>
		/// <param name="token">The token that was found.</param>
		/// <returns>The detail information that was parsed from the token</returns>
		public TokenMatch Parse(Token token)
		{
			TokenMatch result = new TokenMatch(this.Name, token.Value);

			if (!string.IsNullOrEmpty(this.Value))
			{
				result.Data["value"] = this.Value;
			}
			else if (this.matchMap.Count != 0)
			{
				Match m = Regex.Match(token.Value, this.MatchPattern);
				for (int i = 1; i < m.Groups.Count; i++)
				{
					string name = this.matchMap[i.ToString()];
					if (name != null)
					{
						string value = m.Groups[i].Value;
						result.Data[name] = value;
					}
				}
			}

			return result;
		}

		internal XmlElement ToXml(XmlDocument ownerDoc)
		{
			XmlElement self = ownerDoc.CreateElement("token", ParserConfig.EcmaDocNamespace);
			self.SetAttribute("name", Name);
			self.SetAttribute("handler", Handler);
			if (!string.IsNullOrEmpty(Value))
			{
				self.SetAttribute("value", Value);
			}
			else
			{
				self.SetAttribute("match", MatchPattern);
			}

			return self;
		}
	}
}